package org.brisling.workflow.service;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.brisling.base.domain.ListDomain;
import org.brisling.base.service.BaseService;
import org.brisling.common.ConstSysParam;
import org.brisling.common.util.LongUtil;
import org.brisling.common.util.StringUtil;
import org.brisling.sysman.domain.Permissions;
import org.brisling.sysman.queryService.QueryPermissionService;
import org.brisling.workflow.domain.FlowTaskConfig;
import org.brisling.workflow.repository.FlowTaskConfigRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;


@RestController
@RequestMapping("/flowTaskConfig")
/**
 * 用戶后台服務service
 * @Author : jackson wang
 * @Date   : 2015年6月8日 下午4:18:01
 * @version: 1.0
 */
public class FlowTaskConfigService extends BaseService<FlowTaskConfig>{
	
	@Autowired
	private FlowTaskConfigRepo baseRepo;
	
	@Autowired
	private WorkFlowDefinitionService definitionService;
	
	
	@Autowired
	private QueryPermissionService qryPermissionService;
	
	
	@PersistenceContext(unitName=ConstSysParam.SUBSYSTEM_SYSMAN)
	@Autowired
	protected void setEntityManager(EntityManager entityManager){
		this.entityManager = entityManager;
		this.subSystem = ConstSysParam.SUBSYSTEM_WORKFLOW;
		this.clazz = FlowTaskConfig.class;
		this.moduleName = ConstSysParam.MODULE_FLOW_TASK_CONFIG;
	}
	
	@SuppressWarnings("unused")
	@Autowired
	private WorkFlowDefinitionService definitonService;	
	
	/**
	 * 获取业务主页面 
	 * @return
	 */
	@RequestMapping("/mainPage.action")
	public ModelAndView getMainPage(){
		return new ModelAndView("/workflow/flowTaskConfig/main");
	}
	
	/**
	 * 获取业务编辑页面
	 * @return
	 */
	@RequestMapping("/editPage.action")
	public ModelAndView getEditPage(){
		return getBizEditPage();
	}
	
	
	
	/**
	 * 分页查询流程节点配置信息
	 * @param page
	 * @param rows
	 * @param procDefinitionName
	 * @param sort
	 * @return
	 */
	@RequestMapping("/getByDefinitionIdListDomain.action")
	public ListDomain<FlowTaskConfig> getDefinitionListDomain(
			@RequestParam(value="page",required=false) String page,
			@RequestParam(value="rows",required=false) String rows,			
			@RequestParam(value="procDefinitionId",required=false) String procDefinitionId,
			@RequestParam(value="sort",required=false) String sort){
		
		
		
		ListDomain<FlowTaskConfig> listDomain= new ListDomain<FlowTaskConfig>();
		listDomain.setRows(new ArrayList<FlowTaskConfig>());
		listDomain.setTotal(0l);
		if((procDefinitionId!=null)&&(procDefinitionId.trim().length()>0)){
			//查找关联业务模块
			Permissions p = qryPermissionService.getOneByField("flowid", procDefinitionId);
			
			
			//查找已有流程定义map
			Map<String,FlowTaskConfig> map = getConfigNodeMap(page, rows, procDefinitionId, sort,p);
			
			if( (map==null) || (map.isEmpty())){
				//查找activity流程定义文件中的节点定义
				map = getDefinitionNodeMap(procDefinitionId,p);
			}
			
			if(!map.isEmpty()){
				List<FlowTaskConfig> lists = new ArrayList<FlowTaskConfig>();
				for(Entry<String, FlowTaskConfig> node:map.entrySet()){
					lists.add(node.getValue());					
				}
				Collections.sort(lists);
				listDomain.setRows(lists);
				listDomain.setTotal((long) lists.size());
			}
		}
		return listDomain;
			
	}
	
	/**
	 * 查询流程节点定义中存在的流程节点 及流程节点配置中已保存节点，合并后返回前端
	 * @param page	页号
	 * @param rows	行数
	 * @param procDefinitionId	流程文件定义id	
	 * @param sort	排序字段
	 * @return
	 */
	@RequestMapping("/getLackDefinition.action")
	public ListDomain<FlowTaskConfig> getLackDefinitionListDomain(
			@RequestParam(value="page",required=false) String page,
			@RequestParam(value="rows",required=false) String rows,			
			@RequestParam(value="procDefinitionId",required=false) String procDefinitionId,
			@RequestParam(value="sort",required=false) String sort){
		
		
		
		ListDomain<FlowTaskConfig> listDomain= new ListDomain<FlowTaskConfig>();
		listDomain.setRows(new ArrayList<FlowTaskConfig>());
		listDomain.setTotal(0l);
		if((procDefinitionId!=null)&&(procDefinitionId.trim().length()>0)){
			//查找关联业务模块
			Permissions p = qryPermissionService.getOneByField("flowid", procDefinitionId);
			//查找已有流程定义map
			Map<String,FlowTaskConfig> map = getConfigNodeMap(page, rows, procDefinitionId, sort,p);
			
			
			//查找activity流程定义文件中的节点定义
			Map<String,FlowTaskConfig> defMap = getDefinitionNodeMap(procDefinitionId,p);
			
			
			if(map==null){
				//当前尚未定义节点
				map = defMap;
			}else{
				if(defMap!=null){
					for(FlowTaskConfig fc:defMap.values()){
						
						//判断已配置节点中是否已存在流程定义文件中的节点
						if(!map.containsKey(fc.getActivityId())){
							map.put(fc.getActivityId(), fc);
						}
					}
				}
			}
			
			List<FlowTaskConfig> lists = new ArrayList<FlowTaskConfig>();
			for(Entry<String, FlowTaskConfig> node:map.entrySet()){
				lists.add(node.getValue());					
			}
			Collections.sort(lists);
			listDomain.setRows(lists);
			listDomain.setTotal((long) lists.size());
			
		}
		return listDomain;
			
	}
	
	
	/**
	 * 获取流程节点配置定义map
	 * @param page	页号
	 * @param rows	行数
	 * @param procDefinitionId	流程定义id
	 * @param sort	排序字段
	 * @return
	 */
	private Map<String,FlowTaskConfig> getConfigNodeMap(String page,String rows,String procDefinitionId,String sort,Permissions p){
		Map<String,FlowTaskConfig> map = new HashMap<String,FlowTaskConfig>();
		
		//查询当前模块中保存的流程节点配置信息
		Page<FlowTaskConfig> pageList = this.getDefinitionList(page, rows, procDefinitionId, sort);
		if(pageList!=null&&pageList.getTotalElements()>0){
			
			//获取完整业务编码及业务名称
			String  fullBizcode = null;
			String  bizname = null;
			
			if(p!=null){
				fullBizcode = p.getFullBizcode();
				bizname = p.getName();
			}
			
			
			List<FlowTaskConfig> lists = pageList.getContent();
			//循环保存查询结果
			for(int i=0;i<pageList.getTotalElements();i++){
				FlowTaskConfig _fc =lists.get(i);
				//更新业务编码及业务名称
				_fc.setFullBizcode(fullBizcode);
				_fc.setBizname( bizname);
				map.put(_fc.getActivityId(), _fc);
//				listDomain.setTotal(pageList.getTotalElements());
//				listDomain.setRows(pageList.getContent());
			}
		}
		
		return map;
	}
	/**
	 * 获取流程定义文件节点map
	 * @param procDefinitionId	流程定义id
	 * @param p					关联业务模块
	 * @return	Map<String,FlowTaskConfig>
	 */
	private Map<String,FlowTaskConfig> getDefinitionNodeMap(String procDefinitionId,Permissions p){
		//查找activity流程定义文件中的节点定义
		
		Map<String,FlowTaskConfig> map = new HashMap<String,FlowTaskConfig>();
		Map<String,String> nodeMap = definitionService.findTaskDefinitionByProcDefId(procDefinitionId);
		
		String  fullBizcode = null;
		String  bizname = null;
		
		if(p!=null){
			fullBizcode = p.getFullBizcode();
			bizname = p.getName();
		}
		
		if(!nodeMap.isEmpty()){
			for(String nodeId:nodeMap.keySet()){						
				
				FlowTaskConfig ftc = new FlowTaskConfig(
						procDefinitionId,
						nodeId,
						nodeMap.get(nodeId).toString(),
						fullBizcode,
						bizname,
						1);						
				map.put(nodeId, ftc);
				
			}
		}
		
		return map;
	}
	
	/**
	 * 分页查询用户列表页面
	 * @param procDefinitionName 流程定义名称
	 * @param page	页号
	 * @param rows	每页行数
	 * @param sort	排序字段
	 * @return	 
	 */
	@RequestMapping("/getList.action")
	public List<FlowTaskConfig> getList(){
		return this.getAll(defaultSort);
		
	}
	
	
	
	/**
	 * 分页查询流程配置列表页面
	 * @param page 页号
	 * @param rows 每页行数
	 * @param procDefinitionName 流程定义名称
	 * @param sort 排序字段
	 * @return <code>org.springframework.data.domain.Page</code> spring分页结果集
	 */
	private Page<FlowTaskConfig> getDefinitionList(
			String page, String rows, String procDefinitionId,String sort){
		
			Integer _page = LongUtil.getIntValue(page, null);
			Integer _pageSize = LongUtil.getIntValue(rows, null);			
			Page<FlowTaskConfig> pageList= baseRepo.getByProcDefinitionId(procDefinitionId, getPageRequest(_page,_pageSize,sort));
			return pageList;
			
	}
	
	/**
	 * 根据角色名称查找角色集合
	 * @param roleNames
	 * @return
	 */
	public List<FlowTaskConfig> getRoleListByRoleNames(List<String> roleNames){
		
		return super.getListByNames(roleNames);
			
	}
	
	/**
	 * 根据角色名称查找角色编码
	 * @param roleNames
	 * @return
	 */
	public List<String> getRoleIdsByRoleNames(List<String> roleNames){
		
		List<FlowTaskConfig> roles = this.getRoleListByRoleNames(roleNames);
		
		
		return StringUtil.getStringIdList(roles);
	}
	
	/**
	 * 删除人员信息
	 * @param id
	 */
	@RequestMapping("/del.action")
	public String delRow(@RequestParam(value="id",required=false) Long id){
		return super.del(id);		 
	}
	
	
	/**
	 * 保存流程节点配置
	 * @param id
	 */
	@RequestMapping("/saveList.action")
	public List<FlowTaskConfig> saveList(
			@RequestBody(required=false) String body){
		
		String _body = null;
		try {
			_body = java.net.URLDecoder.decode(body,"UTF-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		};
		
		ObjectMapper mapper = new ObjectMapper();
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);	
		JavaType _javaType = mapper.getTypeFactory().constructCollectionType(List.class, FlowTaskConfig.class);
		List<FlowTaskConfig> list = null;
		try {
			list =  mapper.readValue(_body, _javaType);
			
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}		
		
		if(list!=null){			
			if(list!=null && (list.size()>0)){				
				
				list =(List<FlowTaskConfig>) baseRepo.save(list);
				
			}	
			return list;
		}
		return null;
	}
	
	/**
	 * 保存单个流程节点配置
	 * @param id
	 */
	@RequestMapping("/save.action")
	public FlowTaskConfig save(@RequestBody(required=false) String body){
		
		
		return super.save(body, clazz);
	}
	
}
